package com.laivi.basic.module.syncdata;

import java.util.List;

import com.laivi.basic.common.constants.Constant;
import com.laivi.basic.model.Property;
import com.laivi.basic.model.datastruct.ValueMap;
import com.laivi.basic.model.syncdata.DestDatabase;
import com.laivi.basic.model.syncdata.SrcDatabase;
import com.laivi.basic.module.sql.DBDao;
import com.laivi.basic.module.sql.SqlDao;
import com.laivi.basic.type.SyncType;
import com.laivi.basic.util.DataUtil;
import com.laivi.basic.util.SqlUtil;

/**
 * @author laivi.zhu@gmail.com
 * @date 2014-7-4
 * description:
 */
public class DBToDBTask extends Task {
	private SrcDatabase src;
	private DestDatabase dest;
	private DBDao srcDao;
	private DBDao destDao;
	private String lastKeyValue;
	private static Property prop=new Property("/syncdata.properties");
	
	public DBToDBTask(){
	}
	
	public DBToDBTask(String name,long period,SrcDatabase src,DestDatabase dest){
		super(name,period);
		this.src = src;
		this.dest = dest;
		this.destDao=new SqlDao(dest.getUrl(),dest.getUser(),dest.getPassword());
		this.srcDao=new SqlDao(src.getUrl(),src.getUser(),src.getPassword());
	}
	

	@Override
	public void execute() throws Exception {
		int total=0;
		int time=0;
		//获取同步记录数量
		if(!dest.getType().name().equals(SyncType.ALL.name()) &&!DataUtil.isEmpty(src.getKeyField())){
			lastKeyValue=prop.get(this.getName());
			total=srcDao.countParam(src.getSql(), lastKeyValue);
		}else{
			total=srcDao.count(src.getSql());
		}
		//为了避免数据一次插入太大,所以分页同步,计算同步次数
		if(total%Constant.SyncData.SYNC_RECORD_PAGE==0){
			time=total/Constant.SyncData.SYNC_RECORD_PAGE;
		}else{
			time=total/Constant.SyncData.SYNC_RECORD_PAGE+1;
		}
		if(time!=0 && dest.getType().name().equals(SyncType.ALL.name())){
			//如果是全量同步，则先删除再同步
			destDao.delete(dest.getTable(), Constant.EMPTY);
		}else if(dest.getType().name().equals(SyncType.UPDATE.name())){
			//如果是更新模式，则先更新再增量同步
			update();
		}
		//分页同步
		for(int i=1;i<=time;i++){
			List<ValueMap> srcList=null;
			if(!dest.getType().name().equals(SyncType.ALL.name()) &&!DataUtil.isEmpty(src.getKeyField())){
				srcList=srcDao.queryParam(srcDao.getBreakSql(src.getSql(), i, Constant.SyncData.SYNC_RECORD_PAGE),lastKeyValue);
			}else{
				srcList=srcDao.query(srcDao.getBreakSql(src.getSql(), i, Constant.SyncData.SYNC_RECORD_PAGE));
			}
			if(srcList!=null && srcList.size()>0){
				destDao.add(dest.getTable(),srcList);
			}
		}
		if(total>0 && !dest.getType().name().equals(SyncType.ALL.name()) && !DataUtil.isEmpty(src.getKeyField())){
			lastKeyValue=String.valueOf(destDao.fun(dest.getTable(),Constant.EMPTY, "max", src.getKeyField()));
			prop.addAndSave(this.getName(), lastKeyValue);
		}
	}
	
	public void update(){
		int total=destDao.count(dest.getTable(), Constant.EMPTY);
		int time=0;
		if(total%Constant.SyncData.SYNC_RECORD_PAGE==0){
			time=total/Constant.SyncData.SYNC_RECORD_PAGE;
		}else{
			time=total/Constant.SyncData.SYNC_RECORD_PAGE+1;
		}
		for(int i=1;i<=time;i++){
			List<ValueMap> destList=destDao.query(destDao.getBreakSql("select "+src.getKeyField()+" from "+dest.getTable(), i, Constant.SyncData.SYNC_RECORD_PAGE));
			List<ValueMap> srcList=srcDao.query(src.getSql().substring(0, src.getSql().indexOf(" where"))+" where "+src.getKeyField()+SqlUtil.toIn(destList, src.getKeyField()));
			destDao.update(dest.getTable(), srcList, src.getKeyField());
		}
	}
		

	public SrcDatabase getSrc() {
		return src;
	}

	public void setSrc(SrcDatabase src) {
		this.src = src;
		srcDao=new SqlDao(src.getUrl(),src.getUser(),src.getPassword());
	}

	public DestDatabase getDest() {
		return dest;
	}

	public void setDest(DestDatabase dest) {
		this.dest = dest;
		destDao=new SqlDao(dest.getUrl(),dest.getUser(),dest.getPassword());
	}
}
